<?php

//eg:1
function my_autoloader($class) {
    //var_dump($class);
    include $class . '.php';
}

spl_autoload_register('my_autoloader');

//eg:2
$class_name = "ShopProduct";
spl_autoload_register(function ($class) {
    var_dump($class);
    $path =$class . '.php';
    $path1 =$class . '.php';

    if(!file_exists($path)){
        throw new Exception("No such file as {$path}");
    }
    include($path);
    include($path1);
    //** 1.查找类** class_exists
    if(! class_exists("ShopProduct")){
        throw new Exception("No such class as {$class_name}");
    }

});


$product = new ShopProduct('The Darkening','Harry','Hunter',12.99);
$cd_product = new CdProdcut('The Darkening','Harry','Hunter',12.99);
print $product->getProducer();
print $product->getSummaryLine();

//** 2.了解类或对象** instanceof
if(get_class($product) == 'ShopProduct'){
    print "\$product is a ShopProduct object<BR/>";
}

//instanceof 对象是否属于ShopProduct家族
if($product instanceof ShopProduct){
    print "\$product is a ShopProduct object<BR/>";
}


//** 3.了解类中的方法** get_class_methods()
print_r(get_class_methods('ShopProduct'));
print "<BR/>";
//调用某个方法之前，先检测该方法是否存在于get_class_methods()返回的数组中，
//更专业的工具，可以使用is_callable() 和 method_exists()来检查。
//is_callable()更高级一些

$method = "getSummaryLine";

if(in_array($method,get_class_methods("ShopProduct"))){
    print $product->$method();
}
//is_callable 检查存在protected和private类方法时，为false
if(is_callable(array($product,$method))){
    print $product->$method();
}

if(method_exists($product, $method)){
    print $product->$method();
}


//** 4.了解类属性** get_class_vars()
//只显示public属性
print_r(get_class_vars("ShopProduct"));
print "\n<BR/>";

//** 5.了解继承 **  get_parent_class()/is_subclass_off()
print get_parent_class('CdProdcut');
print "\n<BR/>";
print get_parent_class('ShopProduct');

//is_subclass_of ,第一个参数 子类对象，第二个参数 父类的名字
if(is_subclass_of($cd_product, "ShopProduct")){
    print "CdProdcut is a  subclass of  ShopProduct";
    print "\n<BR/>";
}


//** 6.方法调用 **  call_user_func()
$return_val = call_user_func("getHello");
echo $return_val;
print "\n<BR/>";

function getHello(){
    return "Hello";
}

$return_val1 =call_user_func(array($cd_product,"getSummaryLine"));
echo $return_val1."\n\n\n<BR/>";


//反射API
//** 检查类 ReflectionClass
$prod_class = new ReflectionClass('CdProdcut');
Reflection::export($prod_class);
print "\n<BR/>";


function classData(ReflectionClass $class){
    $details = "";
    $name = $class->getName();
    //类已经在PHP代码中定义
    if($class->isUserDefined()){
        $details .= "$name is user defined\n<BR/>";
    }
    //如果是内置类
    if($class->isInternal()){
        $details .="$name is built-in\n<BR/>";
    }
    //是否是接口
    if($class->isInterface()){
        $details .="$name is interface\n<BR/>";
    }
    //是否是抽象
    if($class->isAbstract()){
        $details .="$name is  an abstract class\n<BR/>";
    }
    if($class->isFinal()){
        $details .="$name is a final class\n<BR/>";
    }
    //是否可行
    if($class->isInstantiable()){
        $details .="$name can be instantiated\n<BR/>";
    }else{
        $details .="$name can not be instantiated\n<BR/>";
    }
    return $details;
}

$prod_class = new ReflectionClass('CdProdcut');
print classData($prod_class);
print "\n<BR/>";

class  ReflectionUtil{
    static function getClassSource(ReflectionClass $class){
        $path = $class->getFileName();
        $lines = @file($path);
        $from = $class->getStartLine();
        $to = $class->getEndLine();
        $len = $to-$from+1;
        return implode(array_slice($lines, $from-1,$len));
    }
}

print ReflectionUtil::getClassSource(new ReflectionClass('CdProdcut'));



//** 检查方法 ReflectionMethod

$prod_class = new ReflectionClass('CdProdcut');
$methods = $prod_class->getMethods();
print " 检查方法  ReflectionMethod() \n<BR/> \n<BR/>";
foreach($methods as $method){
    print methodData($method);
    print "\n<BR/>-----\n<BR/>";
}

function methodData(ReflectionMethod $method){
    $details = "";
    $name = $method->getName();
    if($method->isUserDefined()){
        $details .="$name is user defined\n<BR/>";
    }

    if($method->isInternal()){
        $details .="$name is  built-in \n<BR/>";
    }

    if($method->isAbstract()){
        $details .="$name is  abstract \n<BR/>";
    }

    if($method->isPublic()){
        $details .="$name is  public \n<BR/>";
    }

    if($method->isProtected()){
        $details .="$name is  protected \n<BR/>";
    }

    if($method->isPrivate()){
        $details .="$name is  private \n<BR/>";
    }

    if($method->isStatic()){
        $details .="$name is  Static \n<BR/>";
    }

    if($method->isFinal()){
        $details .="$name is  Final \n<BR/>";
    }
    if($method->isConstructor()){
        $details .="$name is  Constructor \n<BR/>";
    }

    if($method->returnsReference()){
        $details .="$name returns a reference (as opposed to a value) \n<BR/>";
    }

    return $details;
}


//** 检查方法参数  getParameters()


$method = $prod_class->getMethod("__construct");
$params = $method->getParameters();

print " 检查方法参数  getParameters() \n<BR/> \n<BR/>";
foreach($params as $param){
    //var_dump($param);
    print argData($param);
}


function argData(ReflectionParameter $arg){
    $details = "";
    $name = $arg->getName();
    $class = $arg->getClass();
//var_dump($name,$class);
    if(!empty($class)){
        $classname = $class->getName();
        $details .="\$$name must be a $classname object \n<BR/>";

    }

    if($arg->isPassedByReference()){
        $details .= "\$$name is passed by reference \n<BR/>";
    }

    return $details;

}





